module state_ctrl_02
#(parameter
 [7:0]  MAIN_FUNCTION    = 8'h0,
 [7:0]  SUB_FUNCTION     = 8'h0,
 [7:0]  MAIN_SOLUTION    = 8'h0,
 [7:0]  SUB_SOLUTION     = 8'h0,
 [7:0]  APPLICATION_TYPE = 8'h0,
 [7:0]  MAIN_VERSION     = 8'd0,
 [7:0]  SUB_VERSION      = 8'd0,
 [7:0]  MINI_VERSION     = 8'd0,
 [31:0] VERSION_DATE     = 32'd0
)
(
    input  wire        resetb,
    input  wire        sclk,

    //和通讯模块接口
    input  wire        packet_load,
    input  wire        fpga_rec_flag,
    
    input  wire [3:0]       apb_sel             ,
    input  wire [31:0]      apb_addr            ,
    input  wire             apb_rw_en           ,
    input  wire [31:0]      apb_wdata           ,
    output wire [31:0]      apb_rdata0          ,  
    
    //千兆PHY接口
    input  wire        rec_flag,
    input  wire        rec_error,
       
    //
    input  wire [1:0]  gp0_rx_type,
    input  wire [1:0]  gp1_rx_type,
    //
    input  wire        lock_enable,
    input  wire        locked,
    
    input  wire [3:0]  pll_reset_cnt

);

//******************************************************************/
//               信号定义
//******************************************************************/        
reg         rec_flag_t;
reg  [2:0]  counter,counter_t,counter_tt;
reg         add_flag,add_flag_t,add_flag_tt;
reg         clr_flag,clr_flag_t;
reg         load_flag,load_flag_t;
reg  [8:0]  adder;
reg         cin;
reg         buf_wea;
reg  [3:0]  buf_waddr;
reg  [7:0]  buf_wdata;
reg  [3:0]  buf_raddr;
wire [7:0]  buf_rdata;
reg  [7:0]  state_version;
reg  [15:0] crc_error_sum_1,crc_error_sum_2;
reg  [31:0] pkt_sum_1,pkt_sum_2,pkt_sum_3;
reg         full_crc;
reg         full_pkt;
reg         state_active;

reg         set_d_ok;
reg  [7:0]  state_data;
assign apb_rdata0 = {state_data,state_data,state_data,state_data };
always @(posedge sclk or negedge resetb) begin
    if (!resetb)
        set_d_ok <= 1'b0;
    else if ( apb_sel[0] && apb_addr[27:24] == 12'h100 && apb_rw_en )
        set_d_ok <= 1'b1;
    else
        set_d_ok <= 1'b0;
end

always@(posedge sclk, negedge resetb)
    if(!resetb)
        rec_flag_t<=1'b0;
    else
        rec_flag_t<=rec_flag;

always@(posedge sclk)
    if(apb_addr[15:0]==16'h0000 && set_d_ok && apb_wdata[7:0]==8'h00 && fpga_rec_flag=='d1)
        clr_flag<=1'b1;
    else 
        clr_flag<=1'b0;

always@(posedge sclk)
    if(apb_addr[15:0]==16'h0000 && set_d_ok && apb_wdata[7:0]==8'h02)
        load_flag<=1'b1;
    else
        load_flag<=1'b0;

always @(posedge sclk or negedge resetb)
    if(!resetb)
        pkt_sum_3<=0;
    else if(packet_load)
        pkt_sum_3<=pkt_sum_1;

reg add_1,add_2;
// wire add;
always @(posedge sclk or negedge resetb)
    if(!resetb)
        add_1<=0;
    else if(rec_flag_t=='d0 && rec_flag=='d1 && full_pkt=='d0)
        add_1<= 1;
    else 
        add_1<= 0;
always @(posedge sclk or negedge resetb)
    if(!resetb)
        add_2<=0;
    else if(clr_flag && add_1)
        add_2<= 1;
    else 
        add_2 <= 0;

// assign add = add_1 || add_2;

always @(posedge sclk or negedge resetb)
    if(!resetb)
        pkt_sum_1<=0;
    else if(clr_flag)
        pkt_sum_1<= pkt_sum_1 - pkt_sum_3 ;
    else if( add_1 || add_2)
        pkt_sum_1<= pkt_sum_1 + 1'b1;


always @(posedge sclk)
    if(clr_flag)
        crc_error_sum_1<='d0;
    else if(rec_flag_t=='d0 && rec_flag=='d1 && rec_error=='d1 && full_crc=='d0)//crc_error_sum_1<16'HFFFF)
        crc_error_sum_1<=crc_error_sum_1+1'b1;

always @(posedge sclk)
    if((&crc_error_sum_1[15:1])=='d1)
        full_crc<='d1;
    else 
        full_crc<='d0;

always @(posedge sclk)
    if((&pkt_sum_1[31:1])=='d1)
        full_pkt<='d1;
    else 
        full_pkt<='d0;        

always @(posedge sclk)
    if(clr_flag)
        pkt_sum_2<='d0;
    else if(load_flag)
        pkt_sum_2<= pkt_sum_3;

always @(posedge sclk)
    if(clr_flag)
        crc_error_sum_2<='d0;
    else if(load_flag)
        crc_error_sum_2<=crc_error_sum_1;

always @(posedge sclk)
    if (apb_sel[0] && apb_addr[27:16] == 12'h100 )
        state_active <= 1;
    else
        state_active <= 0;
        
always @(posedge sclk)
    if (state_active == 0)
        state_data <= 0;
    else
        case(apb_addr[7:0])
            'h00: state_data <= crc_error_sum_2[7:0];
            'h01: state_data <= crc_error_sum_2[15:8];
            'h02: state_data <= pkt_sum_2[7:0];
            'h03: state_data <= pkt_sum_2[15:8];
            'h04: state_data <= pkt_sum_2[23:16];
            'h05: state_data <= pkt_sum_2[31:24];
            'h30: state_data <= gp0_rx_type;
            'h31: state_data <= gp1_rx_type;
            'h40: state_data <= MAIN_FUNCTION;
            'h41: state_data <= SUB_FUNCTION;
            'h42: state_data <= MAIN_SOLUTION;
            'h43: state_data <= SUB_SOLUTION;
            'h44: state_data <= APPLICATION_TYPE;
            'h45: state_data <= MAIN_VERSION;
            'h46: state_data <= SUB_VERSION;
            'h47: state_data <= MINI_VERSION;
            'h48: state_data <= VERSION_DATE[31:24];
            'h49: state_data <= VERSION_DATE[23:16];
            'h4A: state_data <= VERSION_DATE[15:8];
            'h4B: state_data <= VERSION_DATE[7:0];

            /*
            'h54: state_data <= id[63:56];
            'h55: state_data <= id[55:48];
            'h56: state_data <= id[47:40];
            'h57: state_data <= id[39:32];
            'h58: state_data <= id[31:24];
            'h59: state_data <= id[23:16];
            'h5a: state_data <= id[15:8];
            'h5b: state_data <= id[7:0];
            */

            // 'h60: state_data <= flash_status_L_rd;
            //'h61: state_data <= flash_status_H_rd;

            //'h62: state_data <= pll_reset_cnt;
            //'h63: state_data <= phy_reset_cnt;

            'h70: state_data <= lock_enable;
            'h71: state_data <= locked;

            default state_data<='d0;
        endcase

endmodule
